#pragma once
#include <iostream>
#include <queue>
#include "thread.hpp"
#include "lockGuard.hpp"

int max_thread_num = 5;

template <class T>
class threadPool
{
    bool isQueueEmpty()
    {
        return _task_queue.empty();
    }

    void cond_Wait()
    {
        pthread_cond_wait(&_cond, &_mutex);
    }

    T getTask()
    {
        T tmp = _task_queue.front();
        _task_queue.pop();
        return tmp;
    }

public:
    static void *routine(void *args)
    {
        threadData *pdata = (threadData *)args;
        threadPool<T> *pthis = (threadPool<T> *)pdata->_args;

        while (true)
        {
            T task;
            {
                lockGuard lockguard(&pthis->_mutex);
                while (pthis->isQueueEmpty())
                    pthis->cond_Wait();
                task = pthis->getTask();
            }
            task(pdata->_name);
        }
    }

    threadPool(int num = max_thread_num)
        : _thread_num(num)
    {
        pthread_mutex_init(&_mutex, nullptr);
        pthread_cond_init(&_cond, nullptr);

        for (int i = 0; i < _thread_num; ++i)
        {
            _threads.push_back(new Thread(i, routine, this));
        }
    }

    ~threadPool()
    {
        for (auto &it : _threads)
        {
            it->Join();
            delete it;
        }
    }

    void run()
    {
        for (auto &it : _threads)
        {
            it->Start();
        }
    }

    void pushTask(const T &task)
    {
        lockGuard lockGuard(&_mutex);
        _task_queue.push(task);
        pthread_cond_signal(&_cond);
    }

private:
    vector<Thread*> _threads; // 线程池
    int _thread_num;         // 线程池的数量
    queue<T> _task_queue;    // 临界资源区（交易场所）
    pthread_mutex_t _mutex;  // 锁
    pthread_cond_t _cond;    // 条件变量
};
